package netbay;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import com.jcraft.jsch.UserInfo;

public class SFTPManager {

	public static String SFTPuser;
	public static String SFTPhost;
	public static Integer SFTPport;
	public static String SFTPprivateKeyPath;
	public static String SFTPpassPhrase;
	public static boolean SFTPknowHostStrict;

	public static Integer sftpRetryChance = 3;
	public static Integer sftpRetryDelay = 10;

	public static String SFTPsendPath = "/DropBox/IN";
	public static String SFTPrecvPath = "/Outbound/Encrypted";

	public static String SFTPrecvTempDir = "/home/blinding/Desktop/JPMCStore";

	private ChannelSftp mySftp = null;

//	public static void main(String arg[]) {
//
//		String configPath = "./WebContent/WEB-INF/config.properties";
//		NetbayUtility.init(configPath);
//		ChannelSftp cs = null;
//
//			SFTPManager manager = new SFTPManager();
//			System.out.println(manager.sendSFTPFile(new File("/home/blinding/Desktop/testfile/checking"), "checking"));
//			
//	}

	public static String getJPMCIp() {
		InetAddress address = null;
		try {
			address = InetAddress.getByName(SFTPManager.SFTPhost);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}

		if (address != null)
			return address.getHostAddress();
		else
			return null;
	}

	public boolean removeSFTPFile(String fileName) {
		boolean operateSucceed = false;
		ChannelSftp cs = null;
		for (int i = 0; !operateSucceed && i < SFTPManager.sftpRetryChance; ++i) {

			try {
				cs = getChannelSFTP();
				cs.rm(SFTPrecvPath + "/" + fileName);
				operateSucceed = true;
			} catch (SftpException e) {
				try {
					Thread.sleep(SFTPManager.sftpRetryDelay * 1000);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
				e.printStackTrace();
			} catch (JSchException e) {
				try {
					Thread.sleep(SFTPManager.sftpRetryDelay * 1000);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
				e.printStackTrace();
			}
		}
		
		if(cs != null && !cs.isConnected())
		{
			try {
				cs.getSession().disconnect();
			} catch (JSchException e) {
				e.printStackTrace();
			}
		}


		return operateSucceed;
	}

	public boolean getSFTPFile(String fileName, File desFile) {

		if (!desFile.exists()) {
			try {
				desFile.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		boolean operateSucceed = false;
		ChannelSftp cs = null;

		for (int i = 0; !operateSucceed && i < SFTPManager.sftpRetryChance; ++i) {

			try {
				cs = getChannelSFTP();

				FileOutputStream fos = new FileOutputStream(desFile);
				cs.get(SFTPrecvPath + "/" + fileName, fos);
				operateSucceed = true;
			} catch (SftpException e) {
				try {
					Thread.sleep(SFTPManager.sftpRetryDelay * 1000);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
				e.printStackTrace();
			} catch (JSchException e) {
				try {
					Thread.sleep(SFTPManager.sftpRetryDelay * 1000);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
				e.printStackTrace();
			} catch (FileNotFoundException e) {
				try {
					Thread.sleep(SFTPManager.sftpRetryDelay * 1000);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
				e.printStackTrace();
			}
		}
		
		if(cs != null && !cs.isConnected())
		{
			try {
				cs.getSession().disconnect();
			} catch (JSchException e) {
				e.printStackTrace();
			}
		}

		return operateSucceed;
	}

	public boolean sendSFTPFile(File srcFile, String desName) {

		boolean operateSucceed = false;
		ChannelSftp cs = null;
		for (int i = 0; !operateSucceed && i < SFTPManager.sftpRetryChance; ++i) {

			try {
				cs = getChannelSFTP();
				InputStream inStream = null;
				inStream = new FileInputStream(srcFile);
				cs.put(inStream, SFTPsendPath + "/" + desName);

				operateSucceed = true;
			} catch (SftpException e) {
				try {
					Thread.sleep(SFTPManager.sftpRetryDelay * 1000);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
				e.printStackTrace();
			} catch (JSchException e) {
				try {
					Thread.sleep(SFTPManager.sftpRetryDelay * 1000);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
				e.printStackTrace();
			} catch (FileNotFoundException e) {
				try {
					Thread.sleep(SFTPManager.sftpRetryDelay * 1000);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
				e.printStackTrace();
			}
			// finally{
			// if(cs != null)
			// cs.
			// }
		}
		
		if(cs != null && !cs.isConnected())
		{
			try {
				cs.getSession().disconnect();
			} catch (JSchException e) {
				e.printStackTrace();
			}
		}

		return operateSucceed;

	}

	public List<String> lsForFiles() {

		List<String> files = null;

		Vector lsResult = null;

		boolean operateSucceed = false;
		
		ChannelSftp cs = null;

		for (int i = 0; !operateSucceed && i < sftpRetryChance; ++i) {
			try {

				files = new ArrayList<String>();

				cs = getChannelSFTP();

				lsResult = cs.ls(SFTPrecvPath);

				for (int j = 0; j < lsResult.size(); ++j) {

					Object obj = lsResult.get(j);
					if (obj instanceof com.jcraft.jsch.ChannelSftp.LsEntry) {
						String fileName = ((com.jcraft.jsch.ChannelSftp.LsEntry) obj)
								.getFilename();
						if (!fileName.equalsIgnoreCase(".")
								&& !fileName.equalsIgnoreCase("..")) {
							files.add(fileName);
						}
					}
				}

				operateSucceed = true;

			} catch (JSchException e) {
				e.printStackTrace();
			} catch (SftpException e) {
				e.printStackTrace();
			}
		}
		
		if(cs != null && !cs.isConnected())
		{
			try {
				cs.getSession().disconnect();
			} catch (JSchException e) {
				e.printStackTrace();
			}
		}


		return files;
	}

	private ChannelSftp getChannelSFTP() throws JSchException, SftpException {

		if(mySftp != null && !mySftp.isConnected())mySftp.connect();
		
		if (mySftp == null || !mySftp.isConnected()) {

			JSch jSch = new JSch();
			byte[] prvkey = null;

			// System.out.println();

			byte[] passPhrase = SFTPpassPhrase.getBytes();

			try {

				prvkey = readMyPrivateKeyFromFile();
				// Private key must be byte array

				// passPhrase = readMyPassPhraseFromFile();
				// Private key must be byte array
			} catch (IOException e) {
				e.printStackTrace();
			}

			// System.out.println(" read prv key ");

			jSch.addIdentity(SFTPuser, // String userName
					prvkey, // byte[] privateKey
					null, // byte[] publicKey
					passPhrase // byte[] passPhrase
			);

			// System.out.println("finish read prv key ");

			Session session = jSch.getSession(SFTPuser, SFTPhost, SFTPport);

			UserInfo ui = new MyUserInfo(SFTPManager.SFTPpassPhrase); // MyUserInfo
																		// implements
																		// UserInfo
			session.setUserInfo(ui);
			java.util.Properties config = new java.util.Properties();

			if (!SFTPknowHostStrict) {
				config.put("StrictHostKeyChecking", "no");
				session.setConfig(config);
			}

			session.connect();
			Channel channel = session.openChannel("sftp");
			ChannelSftp sftp = (ChannelSftp) channel;
			sftp.connect();

			 System.out.println("successfully connect with sftp");
			// sftp.cd("DropBox");
			// sftp.cd("IN");

			mySftp = sftp;

		}

		return mySftp;
	}

	// private byte[] readMyPassPhraseFromFile() throws IOException {
	//
	// File passphrase = new File(SFTPpassphrasePath);
	//
	// System.out.println(passphrase.getAbsolutePath());
	// System.out.println(passphrase.getName());
	//
	// Long fileLen = passphrase.length();
	// FileUtils util = new FileUtils();
	// //util.
	// FileInputStream fileStream = new FileInputStream(passphrase);
	//
	// byte fileContent[] = new byte[fileLen.intValue()];
	// fileStream.read(fileContent);
	//
	// return fileContent;
	//
	// File file = new File(SFTPpassphrasePath);
	//
	// System.out.println(file.getAbsolutePath());
	//
	// byte[] b = new byte[(int) file.length()];
	// try {
	// FileInputStream fileInputStream = new FileInputStream(file);
	// fileInputStream.read(b);
	// for (int i = 0; i < b.length; i++) {
	// System.out.print((char)b[i]);
	// }
	// } catch (FileNotFoundException e) {
	// System.out.println("File Not Found.");
	// e.printStackTrace();
	// }
	// catch (IOException e1)
	// {
	// System.out.println("Error Reading The File.");
	// e1.printStackTrace();
	// }
	//
	// return b;
	//
	// }

	private byte[] readMyPrivateKeyFromFile() throws IOException {

		File prvkey = new File(SFTPprivateKeyPath);

		// System.out.println(prvkey.getAbsolutePath());
		// System.out.println(prvkey.getName());

		Long fileLen = prvkey.length();
		FileInputStream fileStream = new FileInputStream(prvkey);

		byte fileContent[] = new byte[fileLen.intValue()];
		fileStream.read(fileContent);

		// System.out.println();

		return fileContent;

	}
}
